Change the semantics of GetDomainPath so that it always succeeds, regardless of
authoremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Sun, 23 Oct 2005 21:45:15 +0000 (22:45 +0100)
committeremellor@leeni.uk.xensource.com <emellor@leeni.uk.xensource.com>
Sun, 23 Oct 2005 21:45:15 +0000 (22:45 +0100)
whether a domain has been introduced to the store.  Added a separate message
XS_IS_DOMAIN_INTRODUCED and API for that (xs_is_domain_introduced) to determine
whether the domain has really been introduced.  This change means that the
tools can determine the correct domain path earlier in the domain creation
process, which is particularly a factor with live migration, as it allows us
to create the devices earlier in the process, and unpause the new domain before
performing the introduce.  Until recently we already had these features, but
the simplification of the interface between xend and xenstored caused breakage.

No longer clear out the domain path when a domain is introduced -- this was a
hack to work around the recent problematic semantics of GetDomainPath.

Do not write the contents of the info block to the store.  All the configuration
info is written to the /vm path, and anything else in the info block is either
dealt with explicitly or is ephemeral and has no place in the store.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
tools/console/daemon/io.c
tools/python/xen/lowlevel/xs/xs.c
tools/python/xen/xend/XendCheckpoint.py
tools/python/xen/xend/XendDomainInfo.py
tools/xenstore/xenstored_core.c
tools/xenstore/xenstored_core.h
tools/xenstore/xenstored_domain.c
tools/xenstore/xenstored_domain.h
tools/xenstore/xs.c
tools/xenstore/xs.h
xen/include/public/io/xs_wire.h

index 9039a96525a9cb93c51b2a4db7d24946e97c12f5..60e89267fc00d1b22e86ee394bcb8f61d91c5b28 100644 (file)
@@ -301,10 +301,7 @@ static struct domain *create_domain(int domid)
        }
 
        dom->domid = domid;
-
        dom->conspath = xs_get_domain_path(xs, dom->domid);
-       if (dom->conspath == NULL)
-               goto out;
        s = realloc(dom->conspath, strlen(dom->conspath) +
                    strlen("/console") + 1);
        if (s == NULL)
index b5ce2c357bead9dccd4398c4f328022add4ea5d7..1f0dd5fac225cecfd351ad8f89873455e4b28ba1 100644 (file)
@@ -795,11 +795,10 @@ static PyObject *xspy_close(PyObject *self, PyObject *args, PyObject *kwds)
 }
 
 #define xspy_get_domain_path_doc "\n"                  \
-       "Return store path of domain.\n"                \
+       "Return store path of domain, whether or not the domain exists.\n" \
        " domid [int]: domain id\n"                     \
        "\n"                                            \
        "Returns: [string] domain store path.\n"        \
-       "         None if domid doesn't exist.\n"       \
        "Raises RuntimeError on error.\n"               \
        "\n"
 
index 828fd0f2eb4f5488e14fe86db64ec25de04fc0db..4455734952cbee3ffc141a59fb2de46f5069d4d5 100644 (file)
@@ -144,6 +144,8 @@ def restore(xd, fd):
         if handler.store_mfn is None or handler.console_mfn is None:
             raise XendError('Could not read store/console MFN')
 
+        dominfo.unpause()
+
         dominfo.completeRestore(handler.store_mfn, handler.console_mfn)
 
         return dominfo
index 061e7863d5f6b4159bb60aa81d301fd432097f9f..11256f891636eb41586511f55201bada60094518 100644 (file)
@@ -198,7 +198,7 @@ def recreate(xeninfo, priv):
         vm = XendDomainInfo(xeninfo, domid, dompath, True)
 
     except Exception, exn:
-        if True:
+        if priv:
             log.warn(str(exn))
 
         vm = XendDomainInfo(xeninfo, domid, dompath, True)
@@ -223,7 +223,9 @@ def restore(config):
     try:
         vm.construct()
         vm.storeVmDetails()
+        vm.createDevices()
         vm.createChannels()
+        vm.storeDomDetails()
         return vm
     except:
         vm.destroy()
@@ -337,8 +339,8 @@ def dom_get(dom):
         log.debug("domain_getinfo(%d) failed, ignoring: %s", dom, str(err))
     return None
 
-class XendDomainInfo:
 
+class XendDomainInfo:
 
     def __init__(self, info, domid = None, dompath = None, augment = False):
 
@@ -558,13 +560,13 @@ class XendDomainInfo:
 
     def completeRestore(self, store_mfn, console_mfn):
 
+        log.debug("XendDomainInfo.completeRestore")
+
         self.store_mfn = store_mfn
         self.console_mfn = console_mfn
 
         self.introduceDomain()
-        self.create_devices()
         self.storeDomDetails()
-        self.unpause()
         self.refreshShutdown()
 
 
@@ -597,10 +599,6 @@ class XendDomainInfo:
             'memory/target':      str(self.info['memory_KiB'])
             }
 
-        for (k, v) in self.info.items():
-            if v:
-                to_store[k] = str(v)
-
         def f(n, v):
             if v is not None:
                 to_store[n] = str(v)
@@ -1055,6 +1053,10 @@ class XendDomainInfo:
             raise VmError('Creating domain failed: name=%s' %
                           self.info['name'])
 
+        self.dompath = GetDomainPath(self.domid)
+
+        self.removeDom()
+
         # Set maximum number of vcpus in domain
         xc.domain_max_vcpus(self.domid, int(self.info['vcpus']))
 
@@ -1065,8 +1067,6 @@ class XendDomainInfo:
         assert self.store_port is not None
         
         IntroduceDomain(self.domid, self.store_mfn, self.store_port)
-        self.dompath = GetDomainPath(self.domid)
-        assert self.dompath
 
 
     def initDomain(self):
@@ -1105,7 +1105,7 @@ class XendDomainInfo:
 
         self.introduceDomain()
 
-        self.create_devices()
+        self.createDevices()
 
         self.info['start_time'] = time.time()
 
@@ -1209,23 +1209,21 @@ class XendDomainInfo:
             raise
 
 
-    def create_configured_devices(self):
-        for (n, c) in self.info['device']:
-            self.createDevice(n, c)
-
+    ## public:
 
-    def create_devices(self):
+    def createDevices(self):
         """Create the devices for a vm.
 
         @raise: VmError for invalid devices
         """
-        self.create_configured_devices()
+
+        for (n, c) in self.info['device']:
+            self.createDevice(n, c)
+
         if self.image:
             self.image.createDeviceModel()
 
 
-    ## public:
-
     def device_create(self, dev_config):
         """Create a new device.
 
index d9ecefc133f7829b8bd96d968eec8a47582c6bb7..f5b1b014e33dd0d3aaea33486fc86779fc489e53 100644 (file)
@@ -166,6 +166,7 @@ static char *sockmsg_string(enum xsd_sockmsg_type type)
        case XS_SET_PERMS: return "SET_PERMS";
        case XS_WATCH_EVENT: return "WATCH_EVENT";
        case XS_ERROR: return "ERROR";
+       case XS_IS_DOMAIN_INTRODUCED: return "XS_IS_DOMAIN_INTRODUCED";
        default:
                return "**UNKNOWN**";
        }
@@ -1001,16 +1002,6 @@ static void do_rm(struct connection *conn, const char *name)
 }
 
 
-void internal_rm(const char *name)
-{
-       struct node *node = read_node(NULL, name);
-       if (!node) {
-               return;
-       }
-       _rm(NULL, node, name);
-}
-
-
 static void do_get_perms(struct connection *conn, const char *name)
 {
        struct node *node;
@@ -1153,6 +1144,10 @@ static void process_message(struct connection *conn, struct buffered_data *in)
                do_introduce(conn, in);
                break;
 
+       case XS_IS_DOMAIN_INTRODUCED:
+               do_is_domain_introduced(conn, onearg(in));
+               break;
+
        case XS_RELEASE:
                do_release(conn, onearg(in));
                break;
index abcb42c38dbd78b325b8fba7c00afb9bc152fe63..da98a9211d79475367f2ce15bde14e6a0e237743 100644 (file)
@@ -155,9 +155,6 @@ void __attribute__((noreturn)) corrupt(struct connection *conn,
 struct connection *new_connection(connwritefn_t *write, connreadfn_t *read);
 
 
-void internal_rm(const char *name);
-
-
 /* Is this a valid node name? */
 bool is_valid_nodename(const char *node);
 
index 69e429ccfae843b8c9ab767c37cf1164f4a81c82..d2524696177c1c0a1ee4d236a1f3c63666a163ca 100644 (file)
@@ -250,6 +250,11 @@ bool domain_can_write(struct connection *conn)
        return ((intf->rsp_prod - intf->rsp_cons) != XENSTORE_RING_SIZE);
 }
 
+static char *talloc_domain_path(void *context, unsigned int domid)
+{
+       return talloc_asprintf(context, "/local/domain/%u", domid);
+}
+
 static struct domain *new_domain(void *context, unsigned int domid,
                                 unsigned long mfn, int port)
 {
@@ -262,7 +267,7 @@ static struct domain *new_domain(void *context, unsigned int domid,
        domain->port = 0;
        domain->shutdown = 0;
        domain->domid = domid;
-       domain->path = talloc_asprintf(domain, "/local/domain/%d", domid);
+       domain->path = talloc_domain_path(domain, domid);
        domain->interface = xc_map_foreign_range(
                *xc_handle, domain->domid,
                getpagesize(), PROT_READ|PROT_WRITE, mfn);
@@ -272,8 +277,6 @@ static struct domain *new_domain(void *context, unsigned int domid,
        list_add(&domain->list, &domains);
        talloc_set_destructor(domain, destroy_domain);
 
-       internal_rm(domain->path);
-
        /* Tell kernel we're interested in this event. */
         bind.remote_domain = domid;
         bind.remote_port   = port;
@@ -403,25 +406,37 @@ void do_release(struct connection *conn, const char *domid_str)
 
 void do_get_domain_path(struct connection *conn, const char *domid_str)
 {
-       struct domain *domain;
-       unsigned int domid;
+       char *path;
 
        if (!domid_str) {
                send_error(conn, EINVAL);
                return;
        }
 
+       path = talloc_domain_path(conn, atoi(domid_str));
+
+       send_reply(conn, XS_GET_DOMAIN_PATH, path, strlen(path) + 1);
+
+       talloc_free(path);
+}
+
+void do_is_domain_introduced(struct connection *conn, const char *domid_str)
+{
+       int result;
+       unsigned int domid;
+
+        if (!domid_str) {
+                send_error(conn, EINVAL);
+                return;
+        }
+
        domid = atoi(domid_str);
        if (domid == DOMID_SELF)
-               domain = conn->domain;
+               result = 1;
        else
-               domain = find_domain_by_domid(domid);
+               result = (find_domain_by_domid(domid) != NULL);
 
-       if (!domain)
-               send_error(conn, ENOENT);
-       else
-               send_reply(conn, XS_GET_DOMAIN_PATH, domain->path,
-                          strlen(domain->path) + 1);
+       send_reply(conn, XS_IS_DOMAIN_INTRODUCED, result ? "T" : "F", 2);
 }
 
 static int close_xc_handle(void *_handle)
index e8d5ec8c880f18d15317a0ae1028760159f84dc6..b8d839d624b0aed247b9a24572486c2a24be560a 100644 (file)
@@ -25,6 +25,9 @@ void handle_event(void);
 /* domid, mfn, eventchn, path */
 void do_introduce(struct connection *conn, struct buffered_data *in);
 
+/* domid */
+void do_is_domain_introduced(struct connection *conn, const char *domid_str);
+
 /* domid */
 void do_release(struct connection *conn, const char *domid_str);
 
index 22710d5d014f14645518341286780d0c1a5911a4..a817a88077bc5c587c0c42ac9894906cb0656dd0 100644 (file)
@@ -696,13 +696,20 @@ bool xs_introduce_domain(struct xs_handle *h,
                                ARRAY_SIZE(iov), NULL));
 }
 
-bool xs_release_domain(struct xs_handle *h, unsigned int domid)
+static void * single_with_domid(struct xs_handle *h,
+                               enum xsd_sockmsg_type type,
+                               unsigned int domid)
 {
        char domid_str[MAX_STRLEN(domid)];
 
        sprintf(domid_str, "%u", domid);
 
-       return xs_bool(xs_single(h, NULL, XS_RELEASE, domid_str, NULL));
+       return xs_single(h, NULL, type, domid_str, NULL);
+}
+
+bool xs_release_domain(struct xs_handle *h, unsigned int domid)
+{
+       return xs_bool(single_with_domid(h, XS_RELEASE, domid));
 }
 
 char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
@@ -714,6 +721,12 @@ char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
        return xs_single(h, NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
 }
 
+bool xs_is_domain_introduced(struct xs_handle *h, unsigned int domid)
+{
+       return strcmp("F",
+                     single_with_domid(h, XS_IS_DOMAIN_INTRODUCED, domid));
+}
+
 /* Only useful for DEBUG versions */
 char *xs_debug_command(struct xs_handle *h, const char *cmd,
                       void *data, unsigned int len)
index 618e6615a615490931c5d3b5b77127e3738d15cc..f59b1e76f912556816af18c71cc37d370dd4674f 100644 (file)
@@ -140,6 +140,10 @@ bool xs_release_domain(struct xs_handle *h, unsigned int domid);
  */
 char *xs_get_domain_path(struct xs_handle *h, unsigned int domid);
 
+/* Return whether the domain specified has been introduced to xenstored.
+ */
+bool xs_is_domain_introduced(struct xs_handle *h, unsigned int domid);
+
 /* Only useful for DEBUG versions */
 char *xs_debug_command(struct xs_handle *h, const char *cmd,
                       void *data, unsigned int len);
index 88d6b1f2123ac9801c811d55e6efdd88839b1a13..7d96dc813a3da33234a3d312e3dace6349dec379 100644 (file)
@@ -47,6 +47,7 @@ enum xsd_sockmsg_type
     XS_SET_PERMS,
     XS_WATCH_EVENT,
     XS_ERROR,
+    XS_IS_DOMAIN_INTRODUCED
 };
 
 #define XS_WRITE_NONE "NONE"